package com.im.service.config;

import com.im.common.enums.ImUrlRouteWayEnum;
import com.im.common.enums.RouteHashMethodEnum;
import com.im.common.route.RouteHandle;
import com.im.common.route.algorithm.consistenthash.AbstractConsistentHash;
import com.im.service.utils.SnowflakeIdWorker;
import org.I0Itec.zkclient.ZkClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import java.lang.reflect.Method;

@Configuration
public class BeanConfig {

    @Autowired
    private AppConfig appConfig;

    /**
     * 创建一个RouteHandle对象的Bean
     *
     * @return RouteHandle实例
     * @throws Exception
     */
    @Bean
    public RouteHandle routeHandle() throws Exception {
        // 从配置中获取路由方式
        Integer imRouteWay = appConfig.getImRouteWay();
        // 根据路由方式获取对应的枚举对象
        ImUrlRouteWayEnum imUrlRouteWayEnum = ImUrlRouteWayEnum.getHandler(imRouteWay);
        // 获取路由方式对应的类名
        String routWay = imUrlRouteWayEnum.getClazz();
        // 使用反射创建路由方式对应的实例
        RouteHandle routeHandle = (RouteHandle) Class.forName(routWay).newInstance();
        // 如果选择的路由方式是HASH
        if (imUrlRouteWayEnum == ImUrlRouteWayEnum.HASH) {
            // 获取设置一致性哈希方法的Method对象
            Method setHash = Class.forName(routWay).getMethod("setHash", AbstractConsistentHash.class);
            // 获取配置中设置的一致性哈希算法
            Integer consistentHashWay = appConfig.getConsistentHashWay();
            // 根据一致性哈希算法获取对应的枚举对象
            RouteHashMethodEnum hashHandler = RouteHashMethodEnum.getHandler(consistentHashWay);
            // 获取一致性哈希算法对应的类名
            String hashWay = hashHandler.getClazz();
            // 使用反射创建一致性哈希算法对应的实例
            AbstractConsistentHash consistentHash = (AbstractConsistentHash) Class.forName(hashWay).newInstance();
            // 将一致性哈希算法实例设置到路由实例中
            setHash.invoke(routeHandle, consistentHash);
        }
        // 返回路由实例
        return routeHandle;
    }

    /**
     * 创建一个ZkClient对象的Bean
     *
     * @return ZkClient实例
     */
    @Bean
    public ZkClient buildZKClient() {
        // 使用配置中的ZooKeeper地址和连接超时时间创建一个新的ZkClient实例
        return new ZkClient(appConfig.getZkAddr(), appConfig.getZkConnectTimeOut());
    }

    /**
     * 通过 @Bean 注解，将 SnowflakeIdWorker 实例化并交由 Spring 管理
     * 参数 0 表示机器 ID，可以根据实际情况进行配置
     *
     * @return SnowflakeIdWorker实例
     */
    @Bean
    public SnowflakeIdWorker buildSnowflakeSeq() {
        return new SnowflakeIdWorker(0);
    }


}
